package cs304.p3.library.view;
import java.awt.Dimension;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import javax.swing.AbstractButton;
import javax.swing.BorderFactory;
import javax.swing.ButtonModel;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JPasswordField;
import javax.swing.JTextField;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import cs304.p3.library.controller.LoginController;
import cs304.p3.library.framework.IoC;
import cs304.p3.library.framework.LibraryDataAccessContext;
import cs304.p3.library.model.LoginForm;

@SuppressWarnings("serial")
public class LoginDialog extends JDialog{
	
	private MainFrame parent;
	private JTextField usernameField;
    private JPasswordField passwordField;
    private JCheckBox remember;
    
    private LoginController loginController = IoC.resolve(LoginController.class);
    private LoginForm loginForm = loginController.getLoginForm();

	public LoginDialog(MainFrame frame, String title){
		super(frame, title);
		
		parent = frame;
		JLabel usernameLabel = new JLabel("Username: ");
		JLabel passwordLabel = new JLabel("Password: ");
		usernameField = new JTextField(16);
		passwordField = new JPasswordField(16);
		passwordField.setEchoChar('*');
		
		JButton loginButton = new JButton("Switch User");

		JPanel contentPane = new JPanel();
		setContentPane(contentPane);
		
		
		// layout components using the GridBag layout manager
		
		GridBagLayout gb = new GridBagLayout();
		GridBagConstraints c = new GridBagConstraints();
		
		contentPane.setLayout(gb);
		contentPane.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
		
		// place the username label 
		c.gridwidth = GridBagConstraints.RELATIVE;
		c.insets = new Insets(10, 10, 5, 0);
		gb.setConstraints(usernameLabel, c);
		contentPane.add(usernameLabel);
		
		// place the text field for the username 
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.insets = new Insets(10, 0, 5, 10);
		gb.setConstraints(usernameField, c);
		contentPane.add(usernameField);
		
		// place password label
		c.gridwidth = GridBagConstraints.RELATIVE;
		c.insets = new Insets(0, 10, 10, 0);
		gb.setConstraints(passwordLabel, c);
		contentPane.add(passwordLabel);
		
		// place the password field 
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.insets = new Insets(0, 0, 10, 10);
		gb.setConstraints(passwordField, c);
		contentPane.add(passwordField);
		
		// place the login button
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.insets = new Insets(5, 10, 10, 10);
		c.anchor = GridBagConstraints.CENTER;
		gb.setConstraints(loginButton, c);
		contentPane.add(loginButton);
		
		//Read previous saved login
		remember = new JCheckBox("Remember Username");
		loginController.readUserName();
		
		if(loginForm.isRememberUsername()) {
			remember.setSelected(true);
			usernameField.setText(loginForm.getRememberedUserName());
		}
		c.gridwidth = GridBagConstraints.REMAINDER;
		c.insets = new Insets(5, 10, 10, 10);
		c.anchor = GridBagConstraints.CENTER;
		gb.setConstraints(remember, c);
		contentPane.add(remember);
		
		remember.addChangeListener(new ChangeListener(){
			public void stateChanged(ChangeEvent changeEvent) {
				AbstractButton abstractButton = (AbstractButton)changeEvent.getSource();
		        ButtonModel buttonModel = abstractButton.getModel();
		        remember.setSelected(buttonModel.isSelected());
		        loginForm.setRememberUsername(buttonModel.isSelected());
		        loginForm.setUsername(usernameField.getText());
		        loginController.saveUserName();
			}
		});		
		
		loginButton.addActionListener(new ActionListener(){
			
			public void actionPerformed(ActionEvent e){
				login();
			}
			
		});
		
		passwordField.addKeyListener(new KeyListener(){
			
			//int loginCount = 0;

			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_ENTER){
					login();
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}
			
		});
		
		passwordField.addFocusListener(new FocusListener(){

			@Override
			public void focusGained(FocusEvent arg0) {
				passwordField.selectAll();
			}

			@Override
			public void focusLost(FocusEvent arg0) {

			}
			
		});
		
		usernameField.addKeyListener(new KeyListener(){
			
			@Override
			public void keyPressed(KeyEvent e) {
				if(e.getKeyCode() == KeyEvent.VK_ENTER){
					loginController.saveUserName();
					passwordField.requestFocus();
				}
			}

			@Override
			public void keyReleased(KeyEvent e) {
			}

			@Override
			public void keyTyped(KeyEvent e) {
			}
			
		});
		
		usernameField.addFocusListener(new FocusListener(){

			@Override
			public void focusGained(FocusEvent arg0) {
				usernameField.selectAll();
			}

			@Override
			public void focusLost(FocusEvent arg0) {

			}
			
		});
		
		//Finalize and show
		pack();
		setResizable(false);
		Point loc = frame.getLocationOnScreen();
		Dimension d = frame.getSize();
		setLocation(loc.x + (d.width - getWidth())/2, loc.y + (d.height - getHeight())/2);
	  	setDefaultCloseOperation(DISPOSE_ON_CLOSE);
	    setVisible(true);
	    usernameField.requestFocus();
	}
	
	private void login() {
		
		if(loginForm.getUsername().equals(usernameField.getText())){
			parent.appendText("You are already Logged In!");
			setVisible(false);
			dispose();
			return;
		}
		
		loginForm.setRememberUsername(remember.isSelected());
		loginForm.setUsername(usernameField.getText());
		loginForm.setPassword(String.valueOf(passwordField.getPassword()));
		
		loginController.login();
		
		if(loginForm.getUsername().equals(LibraryDataAccessContext.DEFAULT_USERNAME)){
			parent.appendText("Invalid Login\nUsing default login...\n");
		}else parent.appendText("Welcome user: " + loginForm.getUsername());
		//Update Database Table
		parent.updateDBTables();
		System.out.println("DBTables Updated");
		setVisible(false);
		dispose();
	}

}
